import json
import math
from pydantic import BaseModel, ConfigDict
from sqlalchemy import func, select, Select
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional, List

from common.config.database import Base
from common.utils.common_util import SqlalchemyUtil
from common.utils.validate_util import ValidateUtil


class PageResponseModel(BaseModel):
    """
    列表分页查询返回模型
    """

    数据列表: List = []
    页码: Optional[int] = None
    每页条数: Optional[int] = None
    总数: int
    是否有下一页: Optional[bool] = None


class PageUtil:
    """
    分页工具类
    """

    @classmethod
    def get_page_obj(cls, data_list: List, page_num: int, page_size: int):
        """
        输入数据列表data_list和分页信息，返回分页数据列表结果

        :param data_list: 原始数据列表
        :param page_num: 当前页码
        :param page_size: 当前页面数据量
        :return: 分页数据对象
        """
        # 计算起始索引和结束索引
        start = (page_num - 1) * page_size
        end = page_num * page_size

        # 根据计算得到的起始索引和结束索引对数据列表进行切片
        paginated_data = data_list[start:end]
        has_next = True if math.ceil(len(data_list) / page_size) > page_num else False

        result = PageResponseModel(
            数据列表=paginated_data, 页码=page_num, 每页条数=page_size, 总数=len(data_list), 是否有下一页=has_next
        )

        return result

    @classmethod
    async def paginate(cls, db: AsyncSession, query: Select, page_num: int, page_size: int, is_page: bool = False):
        """
        输入查询语句和分页信息，返回分页数据列表结果

        :param db: orm对象
        :param query: sqlalchemy查询语句
        :param page_num: 当前页码
        :param page_size: 当前页面数据量
        :param is_page: 是否开启分页
        :return: 分页数据对象
        """
        #判断 page_num 和 page_size
        if ValidateUtil.is_empty(page_num) :
            page_num = 1

        if ValidateUtil.is_empty(page_size):
            page_size = 10
        if is_page:
            total = (await db.execute(select(func.count('*')).select_from(query.subquery()))).scalar()
            query_result = await db.execute(query.offset((page_num - 1) * page_size).limit(page_size))
            paginated_data = []
            for row in query_result:
                if row and len(row) == 1:
                    paginated_data.append(row[0])
                else:
                    paginated_data.append(row)
            has_next = math.ceil(total / page_size) > page_num
            result_list = []
            for item in paginated_data:
                result_dict=item
                if isinstance(item, tuple):
                    result_dict = item._asdict()
                    # 自动检测并转换JSON字符串
                    for key, value in result_dict.items():
                        if isinstance(value, str) and (value.startswith('[') or value.startswith('{')):
                            try:
                                result_dict[key] = json.loads(value)
                            except json.JSONDecodeError:
                                # 如果转换失败，保留原始值
                                pass
                result_list.append(result_dict)
            result = PageResponseModel(
                数据列表=SqlalchemyUtil.serialize_result(result_list),
                页码=page_num,
                每页条数=page_size,
                总数=total,
                是否有下一页=has_next,
            )
        else:
            query_result = await db.execute(query)
            no_paginated_data = []
            for row in query_result:
                if row and len(row) == 1:
                    no_paginated_data.append(row[0])
                else:
                    no_paginated_data.append(row)
            result = SqlalchemyUtil.serialize_result(no_paginated_data)

        return result


def get_page_obj(data_list: List, page_num: int, page_size: int):
    """
    输入数据列表data_list和分页信息，返回分页数据列表结果

    :param data_list: 原始数据列表
    :param page_num: 当前页码
    :param page_size: 当前页面数据量
    :return: 分页数据对象
    """
    # 计算起始索引和结束索引
    start = (page_num - 1) * page_size
    end = page_num * page_size

    # 根据计算得到的起始索引和结束索引对数据列表进行切片
    paginated_data = data_list[start:end]
    has_next = True if math.ceil(len(data_list) / page_size) > page_num else False

    result = PageResponseModel(
        数据列表=paginated_data, 页码=page_num, 每页条数=page_size, 总数=len(data_list), 是否有下一页=has_next
    )

    return result



@classmethod
async def paginate_orm(cls, db: AsyncSession, query: Select, page_num: int, page_size: int):
    """
    输入查询语句和分页信息，返回分页数据列表结果

    :param db: orm对象
    :param query: sqlalchemy查询语句
    :param page_num: 当前页码
    :param page_size: 当前页面数据量
    :param is_page: 是否开启分页
    :return: 分页数据对象
    """
    #判断 page_num 和 page_size
    if ValidateUtil.is_empty(page_num) :
        page_num = 1

    if ValidateUtil.is_empty(page_size):
        page_size = 10
    total = (await db.execute(select(func.count('*')).select_from(query.subquery()))).scalar()
    query_result = await db.execute(query.offset((page_num - 1) * page_size).limit(page_size))
    query_result=query_result.unique()
    query_result=zhuanhuanorm(query_result)
    has_next = math.ceil(total / page_size) > page_num
    result = dict(
        数据列表=query_result,
        页码=page_num,
        每页条数=page_size,
        总数=total,
        是否有下一页=has_next,
    )
    return result

def zhuanhuanorm(res):
    if ValidateUtil.is_not_empty(res):
        return [zhuanhuan(item) for item in res]

def zhuanhuan(res):
    if all([isinstance(row, Base) for row in res]):
        for row in res:
            return SqlalchemyUtil.serialize_result(row)
